Fix: assert worker concurrency by overlap, not wall-clock - #1509
Conversation
|
Warning Review limit reached
Next review available in: 9 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The 1. The measured mechanism does not reach the observed magnitudeThe PR attributes the flake to macOS For three workers sleeping concurrently,
The measured inflation passes the bound with 35% to spare. To reach 0.49-0.57 s while parallel, a single sleep would have to inflate ~2.5-2.9x, and the measurement found 1.2-1.55x. There is a factor of two unaccounted for. The PR is explicit that the failure was not reproduced ("not reproducible on bare metal even under harsher conditions"). So what was demonstrated is that a mechanism exists which inflates sleeps; what was not demonstrated is that it inflates them enough. "Not a code defect" is the conclusion that justifies deleting the assertion, and that conclusion is not established by this evidence. The alternative it displaces — partial serialisation on the runner — remains equally unproven, but it is the one that predicts 0.49-0.57 s. It should not be dropped in favour of a mechanism whose measured size is half of what is needed. 2. Dropping the assertion removes the property, and a non-magnitude alternative existsAfter this change nothing verifies that the workers run concurrently. If a regression made The new principle says "Assert the property directly — the functional result or an observable effect — instead." This change asserts only the functional result and drops the property. Concurrency has a direct, non-magnitude formulation: have each worker write its own start and end timestamps into its mailbox, and assert the three intervals overlap. That is relational, not a bound — it holds whether a sleep takes 0.2 s or 0.6 s, so it is immune to exactly the over-sleeping this PR identifies, while still failing if the pool serialises. It satisfies the principle rather than being an exception to it. If overlap is rejected for a reason I am not seeing, that reasoning belongs in the PR, because "wall-clock magnitude is a bad proxy" does not by itself imply "assert nothing". 3. The docstring claims coverage the test cannot have
All three workers are registered with Cross-talk and result-routing are therefore not covered, and "at once" is precisely what was just removed. Both claims in the new docstring are unsupported by the new test body. Cheap fix that makes the claim true: give each worker a distinct duration ( Suggested splitThe For the test: make the results distinguishable (3), and replace the deleted bound with an interval-overlap assertion (2) rather than nothing. If the overlap assertion then proves flaky on the macOS runner, that is a much stronger result than this PR currently has — it would be direct evidence for serialisation, which is the open question in #1496. Note that closing #1496 with |
The parallel-execution case asserted elapsed < 0.8*serial — a wall-clock magnitude proxy for "the workers ran concurrently". It flaked ~2% on macOS CI (0/101 Ubuntu), failing at 0.49-0.57 s. A magnitude bound is the wrong shape for a concurrency property: it conflates concurrency with host timer accuracy and scheduling latency. The macOS time.sleep inflation measured under load (0.2 s -> 0.24-0.31 s, 1.2-1.55x) is not enough on its own to reach 0.49-0.57 s for three parallel sleeps (that needs ~2.5-2.9x), and the failure did not reproduce on bare metal — so whether the runner sees worse inflation or partial serialisation remains open. Either way the magnitude bound is the wrong assertion, so it is replaced, not widened. - Each worker records its [begin, end] work window in its mailbox; assert the three windows mutually overlap (latest begin < earliest end). Relational, not a bound — holds whether a sleep takes 0.2 s or 0.6 s, so immune to timer inflation, yet fails if the pool serialises. - Distinct per-worker result tags so result routing/cross-talk is actually verified (previously all returned 200, so misrouting was silent). - Codify the principle in docs/testing.md: off-hardware tests must not assert wall-clock magnitude as a proxy for a non-temporal property. If the overlap assertion itself flakes on the macOS runner, that is direct evidence of serialisation — the open question in hw-native-sys#1496 — a stronger result than the deleted bound gave. Refs hw-native-sys#1496
81b88eb to
c19c79e
Compare
|
All three points taken — revised in c19c79e. 1. Magnitude gap — agreed, the claim was unsupported. Measured inflation (0.2 s → 0.24-0.31 s, 1.2-1.55x) gives elapsed ≈ 0.31 s for three parallel sleeps, ~35% under the 0.48 s bound; reaching 0.49-0.57 s parallel needs ~2.5-2.9x, which was never measured. The commit message and PR description now state this plainly: the root cause (worse VM inflation vs. partial serialisation) is open, not "no defect". Nothing is closed. 2. Overlap, not nothing — the deleted bound is replaced by an interval-overlap check, exactly as described. Each worker writes 3. Distinct results — each worker now returns a unique tag (100, 200, 300); the result check is per-worker, so a misrouted result fails. The docstring's cross-talk / own-result claim now holds. Split — |
|
Re-reviewed
The overlap assertion is strictly stronger than what it replaces: it fails on any serialisation, where the old bound only fired when serialisation was severe enough to cross 0.48 s. If the runner really does serialise at ~2%, this should catch it at ≥2%, with a message that says so directly. One thing left:
|
|
Failing run: https://github.com/hw-native-sys/simpler/actions/runs/30233519385/job/89879523505 |
Summary
test_parallel_wall_timeassertedelapsed < 0.8 * serial— a wall-clock magnitude proxy for "the workers ran concurrently." A magnitude bound is the wrong shape for a concurrency property: it conflates concurrency with host timer accuracy and scheduling latency. So it is replaced, not widened.This is still live, and it taxes unrelated PRs
Not a historical flake — measured frequency and a fresh occurrence:
ut (macos-latest, 3.10)jobs sampled, Jul 20-26test_parallel_wall_timefailures among themut (ubuntu-latest, 3.10)jobs sampledgot 0.54sThat last one landed on
add-mx-fp8-fp4-dtypes— a PR adding FP8/FP4 dtype support, which has nothing to do with fork, shared memory, or scheduling. That is the actual cost of leaving this in: a ~2% chance of a red check on work that cannot have caused it, and a maintainer spending time deciding whether it is theirs.On the root cause: still open, and this PR does not claim otherwise
macOS
time.sleepover-sleeps under load (measured 0.2 s → 0.24-0.31 s), but that is not enough to explain CI's 0.49-0.57 s for three parallel sleeps — that needs ~2.5-2.9x, and the measurement found 1.2-1.55x. The failure also did not reproduce on bare metal under harsher conditions than the runner.So whether the runner sees worse inflation or genuine partial serialisation is unresolved. This PR does not claim "no defect" and does not auto-close #1496.
What does bound the risk is structural rather than empirical:
_SubWorkerPoolis defined in this test file and never importssimpler.worker. Whatever the macOS runner does to three forked processes, no simpler code path is implicated — the old assertion was measuring a host-scheduler property through a POC fixture. That holds whether or not the serialisation is real, which is why it is the sound basis for changing the test now, ahead of an answer.The change
[begin, end]work window in its mailbox; assert the three windows mutually overlap (max(begins) < min(ends)). Relational, not a bound: it holds whether a sleep takes 0.2 s or 0.6 s, so it is immune to the timer inflation identified above, yet fails if the pool serialises.time.monotonic()is system-wide on both Linux and macOS, so the cross-process comparison is valid.200and the assertion wasresult == 200, so a result delivered to the wrong mailbox was silent.docs/testing.md: off-hardware tests must not assert wall-clock magnitude as a proxy for a non-temporal property — with an exception for tests where wall time genuinely is the subject (a timeout firing, a deadline respected).The new assertion is strictly more sensitive than the one it replaces: it fails on any serialisation, where the old bound only fired when serialisation was severe enough to push past 0.48 s.
If it flakes anyway
Then #1496 gets its answer. An overlap failure is direct evidence of serialisation — more than the original investigation produced — and the issue should be reopened with that failure attached rather than a new one filed.
Testing
pre-commit runon both files — markdownlint-cli2, ruff check/format, pyright all passtest_hostsub_fork_shm.pypass (direct invocation; module imports only stdlib +torch)latest_begin > earliest_end→ the overlap assertion trips, so it is not vacuoustaskpolicy -b+ 7 CPU hogs — the regime that inflated sleeps to ~300 ms; overlap stays green, as expected for an inflation-immune assertionut (macos-latest)/ut (ubuntu-latest)confirm greenRefs #1496 (left open pending the macOS answer)